package com.example.demoeasyexcelboot.commons;

import com.alibaba.excel.EasyExcel;
import com.example.demoeasyexcelboot.constants.FileType;
import com.example.demoeasyexcelboot.excel.ImportExcelResult;
import com.example.demoeasyexcelboot.listener.AbstractDataValidListener;
import com.example.demoeasyexcelboot.listener.SimpleDataValidListener;
import com.example.demoeasyexcelboot.processor.ExcelMergeStrategy;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.util.StopWatch;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Objects;

/**
 * @author: FSL
 * @date: 2023/4/12
 * @description: easy excel 工具类
 */
@Slf4j
public class EasyExcelUtil {

    public static <T> ImportExcelResult readExcel(InputStream stream,Class<T> clazz){
        log.info("### 开始读取上传的Excel文件 ###");
        SimpleDataValidListener<T> listener = new SimpleDataValidListener<>(clazz);
        return readExcel(stream,clazz,1,listener);
    }

    public static <T> ImportExcelResult readExcel(InputStream stream, Class<T> clazz, Integer sheetNo, AbstractDataValidListener<T> listener){
        if (Objects.isNull(stream) || Objects.isNull(clazz) || Objects.isNull(listener)) return null;
        if (Objects.isNull(sheetNo) || sheetNo == 0) sheetNo = 1;
        EasyExcel.read(stream,clazz,listener).sheet(sheetNo - 1).doRead();
        return listener.getResult();
    }
    /**
     * @description: 导出一个sheet，带表头
     * @author: FSL
     * @date: 2023/4/12
     * @param outputStream
     * @param dataList  数据集合
     * @param clazz 导出结构体
     * @param sheetName 导入文件的sheet名
     * @return: void
     */
    public static <T> void writeExcel(OutputStream outputStream,List<T> dataList,Class<T> clazz,String sheetName){
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        EasyExcel.write(outputStream,clazz)
                .sheet(sheetName)
                .registerWriteHandler(new ExcelMergeStrategy(clazz))
                .doWrite(dataList);
        stopWatch.stop();
        log.info("导出excel数据：{}条，耗时：{}秒！",dataList.size(),stopWatch.getTotalTimeSeconds());
    }

    /**
     * @description: 导出 Excel文件
     * @author: FSL
     * @date: 2023/4/12
     * @param response
     * @param fileName  文件名
     * @param dataList  需要导出的数据集合
     * @param clazz 导出数据结构体
     * @param sheetName 导入文件的 sheet 名
     * @return: void
     */
    public static <T> void writeExcel(HttpServletResponse response, String fileName, List<T> dataList,Class<T> clazz,String sheetName){
        response.setContentType("application/vnd.ms-excel");
        response.setCharacterEncoding("UTF-8");
        // 防止中文乱码
        String fileNameEncode = null;
        try {
            fileNameEncode = URLEncoder.encode(fileName(fileName),"UTF-8").replaceAll("\\+","%20");
        } catch (UnsupportedEncodingException e) {
            throw new RuntimeException(e);
        }
        response.setHeader("Content-disposition", "attachment;filename=" + fileNameEncode);
        try {
            writeExcel(response.getOutputStream(),dataList,clazz,sheetName);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    private static String fileName(String fileName){
        if (StringUtils.hasText(fileName)){
            return fileName + "." + FileType.XLSX.getSuffix().toLowerCase();
        }
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")) + "." + FileType.XLSX.getSuffix().toLowerCase();
    }
}
